/*
 * IEC103Type.h
 *
 *  Created on: Jan 15, 2021
 *      Author: root
 */

#ifndef IEC103TYPE_H_
#define IEC103TYPE_H_

#include <stdint.h>
#include <sys/types.h>
#include <QString>
#include <QList>

#define _WIN_ 1         // windos 环境标志，用于条件编译
#define CPU_ADDR "01";
#define SETTING_AREA_GINNO "03"
#define POS_ASDU_GROUPNO 16

//03   通用分类标识序号(GIN)--组号
//00   通用分类标识序号(GIN)--条目号
//0A   描述类别(KOD)
//01   通用分类数据描述(GDD)--数据类型:OS8ASCII<ASCII8位码>
//06   通用分类数据描述(GDD)--数据宽度
//01   通用分类数据描述(GDD)--数目::1 后续状态::0
//B6 A8 D6 B5 D7 E9   (GID)数据

#define SETTING_GROUP_NAME "定值"

#define ASDU_CPU_ADDR "01"       // 国电南自保护设备的cpu地址都是“01”
#define ASDU_RII "00"            // 定义一个初始的返回信息表示符号

#define ASDU_TYPE_0A "2A"
#define ASDU_TYPE_15 "15"

#define POS_TYPE 0
#define POS_COT 4
#define POS_FUN 8
#define POS_INF 10
#define POS_RII 12
#define POS_NGD 14
#define POS_GROUP_NO 16
#define POS_GINNO 18
#define POS_KOD 20

//QByteArray asduType = packet.mid(0, 2);
//QByteArray cot = packet.mid(4, 2);
//QByteArray fun = packet.mid(8, 2);
//QByteArray inf = packet.mid(10, 2);
//QByteArray rii = packet.mid(12, 2);
//QByteArray ngd = packet.mid(14, 2);     // 数据集元素的个数，读定值区时只有一个值， 定值组布置一个定值
//QByteArray groupNo = packet.mid(16, 2);
//QByteArray ginNo = packet.mid(18, 2);
//QByteArray kod = packet.mid(20, 2);




// ASDU 的数据集元素的6个成员, 专门描述数据段
struct OneDataSetStruct {
    QString m_ginGroup;
    QString m_ginNo;
    QString m_kod;
    QString m_dataType;
    QString m_dataWidth;
    QString m_dataNum;
    QString m_dataValue;
};

// 定值读取和写入需要使用
typedef struct
{
    //通用分类标识序号GIN
    QString groupNo;    //组号
    QString entryNo;    //条目号

    //描述的类别KOD
    QString kod;

    //通用分类数据描述GDD
    QString datatype;   //数据类型
    QString dataLen;   //每一个数据宽度
    QString number;     //数据个数和后续状态位
    QString data;     //数据
}stDataUnit_GDNZ;     //通用分类数据单元

struct ASDUStruct{
    QString m_serverType;   // 1.服务类型 ， service type = 15 主站发送， 0A ，
    QString m_vsq;          // 2.可变结构限定词
    QString m_cot;          // 3.传送原因
    QString m_addr;         // 4.应用服务单元地址
    QString m_fun;          // 5.功能类型
    QString m_inf;          // 6.信息号
    QString m_rii ;         // 7.由主站端提供，设备只管回一样的
    QString m_ngd;          // 8.数据集数目
    QList<OneDataSetStruct> m_dataSetsList;    // 所有的需要传输的数据

    inline QString asduToQString()
    {
        QString packet;
        packet.append(this->m_serverType + this->m_vsq + this->m_cot + this->m_addr + this->m_fun + this->m_inf + this->m_rii + this->m_ngd);

        // dataSet 部分转 QString
        for(int i=0; i< m_dataSetsList.count(); i++)
        {
            packet.append(this->m_dataSetsList[i].m_ginGroup);
            packet.append(this->m_dataSetsList[i].m_ginNo);
            packet.append(this->m_dataSetsList[i].m_kod);
            packet.append(this->m_dataSetsList[i].m_dataType);
            packet.append(this->m_dataSetsList[i].m_dataWidth);
            packet.append(this->m_dataSetsList[i].m_dataValue);
        }

        return packet;
    }

    inline QByteArray asduToBytes()
    {
        QByteArray packet;
        packet.append(this->m_serverType + this->m_vsq + this->m_cot + this->m_addr + this->m_fun + this->m_inf + this->m_rii + this->m_ngd);

        // dataSet 部分转 QString
        for(int i=0; i< m_dataSetsList.count(); i++)
        {
            packet.append(this->m_dataSetsList[i].m_ginGroup);
            packet.append(this->m_dataSetsList[i].m_ginNo);
            packet.append(this->m_dataSetsList[i].m_kod);
            packet.append(this->m_dataSetsList[i].m_dataType);
            packet.append(this->m_dataSetsList[i].m_dataWidth);
            packet.append(this->m_dataSetsList[i].m_dataValue);
        }

        return packet;
    }
};

#define KOD_REAL_VALUE     "01"    //描述类别  1为实际值                   设定的值
#define KOD_DEFAULT_VALU     "02"    //描述类别  2为缺省值                   默认定值
#define KOD_DIMENSION     "03"    //描述类别  值的量程范围，也就是最小值最大值
#define KOD_ACCURACY     "05"    //描述类别  数据准确度也就是步长
#define KOD_COFFE     "06"    //描述类别  因子
#define KOD_UNIT     "09"    //描述类别                            量纲 也就是单位
#define KOD_DESCRIPTER    "0A"    //描述类别                             描述（定值名字）

//Qt 中使用 QString 类型
#define COT_S2C_TIMESTAMP_STR     "08"      //时间同步
#define COT_S2C_GETALL_START_STR  "09"      //总查询(总召唤)的启动
#define COT_S2C_COMMON_ORDER_STR  "14"   //一般命令
#define COT_S2C_GENERAL_WRITE_STR "28"   //通用分类写命令
#define COT_S2C_GENERAL_READ_STR  "2a"   //通用分类读命令
#define COT_S2C_CIRCLE_SEND_STR "02"


////////字节数据类型//////////////////////////////////////////////////////////////////////////////////////////

// 报文类型标识,ASDU 第一个字节
enum ASDU_TYPE
{
    ASDU_1 = 0x01,
    ASDU_2 = 0x02,
    ASDU_10 = 0x0A,         // 通用分类服务数据报文，在主站发送读取定值的时候子站回该类报文传数据
    ASDU_21 = 0x15,     // 通用分类服务命令，主站发读取定值
    ASDU_40 = 0x28,
    ASDU_41 = 0x29,
    ASDU_42 = 0x2A,
    ASDU_43 = 0x2B,
    ASDU_44 = 0x2C,
    ASDU_45 = 0x2D,
    ASDU_46 = 0x2E,
    ASDU_50 = 0x32,
};


enum CMD_SEND
{
    CMD_RESET_CON,
    CMD_RESET_NUM,
    CMD_RESET_TIMESTAMP,            //对时
    CMD_RESET_EVENT,                //复归命令
    CMD_SETTING_READING,           //定值下载读取
    CMD_SETTING_MODIFY,             //6 定值修改
    CMD_GET_ALL,
    CMD_GET_DATA_LV1,               //获取一级数据
    CMD_GET_DATA_LV2,               //获取二级数据
    CMD_GET_SINGLE_SETTING_VALUE,   // 10 获取单个条目值
    CMD_GENERAL_READ_YX_GROUP_VALUE,
    CMD_GENERAL_READ_YC_GROUP_VALUE,
};

// 读取定值有关信息的返回报文类型,"标题"，"名称","当前值","默认值","最小值","最大值","步长","单位"
enum REPLY_TYPE
{
    REPLY_READ_YB = -2,
    REPLY_READ_SETTINGS_AREA = -1,
    REPLY_TYPE_ALL_GROUP_TITLE = 0,
    REPLY_READ_SETTINGS_NAME = 1,
    REPLY_READ_SETTINGS_CURRVALUE = 2,
    REPLY_READ_DEFAULTVALUE = 3,
    REPLY_READ_SETTINGS_MIN = 4,
    REPLY_READ_SETTINGS_MAX = 5,
    REPLY_READ_SETTINGS_STEP = 6,
    REPLY_READ_SETTINGS_UNIT = 7,
    REPLY_READ_SETTINGS_DATA_TYPE = 8,
    REPLY_READ_SURE_AREA = 9
};


//标志位在报文中的位置
#define CODE_POSI     4        //控制域
#define TYP_POSI      6        //类型标识
#define VSQ_POSI      7        //可变结构限定词
#define COT_POSI      8        //传送原因
#define ADDR_POSI     9        //设备地址
#define FUN_POSI      10       //功能类型
#define INF_POSI      11       //信息序号
#define RII_POSI      12       //返回信息标识符
#define DPI_POSI      12       //双点信息
#define RET_POSI      13       //相对时间   表示装置启动到该元件动作的相对时间，毫秒
#define FAN_POSI      15       //故障序号
#define ASDU_1_TIMESTAMP  13   //ASDU1中四字节时间起始位置
#define ASDU_2_TIMESTAMP  17   //ASDU2中四字节时间起始位置
#define GROUP_POSI        14   //组号
#define TNTRY_POSI        15   //条目号
#define KOD_POSI          16   //描述的类别
#define GDD_POSI          17   //通用分类数据描述
#define GID_POSI          20   //通用分类标识数据
#define NGD_POSI          13   //通用分类数据集数目

// 南自103 ASDU10通用分类数据 标志位在报文中的位置，字节序号从1开始
// 当主站发送 ASDU21（ 15 81(VSQ) 2A(COT) 01(ADDR) F1(FUN) E1(INF) 00(RII) 07(group) 00(TNTRY) 01(KOD) ） 读一个组的全部值会回ASDU10
#define TYP_POSI_NZ     0
#define VSQ_POSI_NZ     2
#define COT_POSI_NZ     4           // 传输原因，典型值  42（0x2A） 对通用分类读命令的有效数据响应， 0x2B 无效
#define ADDR_POSI_NZ    6
#define FUN_POSI_NZ     8
#define INF_POSI_NZ     10
#define RII_POSI_NZ     12
#define NGD_POSI_NZ     14       // 通用分类数据集数目，描述后面接了几个数据元
#define GIN_GROUP_POSI_NZ    16      // 根据定值模板来 选择条目组号
#define GIN_TNTRY_POSI_NZ    18
#define KOD_POSI_NZ     20          // 数据的类别描述，是实际值还是缺省值还是精度
#define GDD_DATA_TYPE_POSI_NZ   22      // 以上为固定的
#define GDD_DATA_SIZE_POSI_NZ   24
#define GDD_DATA_NUM_STA_POSI_NZ    26      //数目和后续状态
#define GID_POSI_NZ     28   // 通用分类标识数据 GID ，占用空间数据宽度* 数据

#define START_10H 0x10    //固定长度报文启动字符
#define START_68H 0x68    //可变长度报文启动字符
#define END_16H   0x16    //结束字符
#define FCB_1     0x20    //帧计数位
#define FCV_1     0x10    //帧计数有效位
#define ACD_1     0x20    //有一级数据上送
#define PRA_1     0x40    //启动报文位　主到从

// kod 描述类别
#define KOD_1     0x01    //描述类别  1为实际值                   设定的值
#define KOD_2     0x02    //描述类别  2为缺省值                   默认定值
#define KOD_3     0x03    //描述类别  值的量程范围，也就是最小值最大值
#define KOD_5     0x05    //描述类别  数据准确度也就是步长
#define KOD_6     0x06    //描述类别  因子
#define KOD_9     0x09    //描述类别                            量纲 也就是单位
#define KOD_10    0X0A    //描述类别                             描述（定值名字）

//功能码定义
#define FNA_S2C_RESET_CON    0   //复位通信功能码
#define FNA_S2C_RESET_NUM    7   //复位帧计数位功能码
#define FNA_S2C_POSTDATA_3   3   //传送数据（发送/确认帧）
#define FNA_S2C_POSTDATA_4   4   //传送数据（发送/无回答帧）
#define FNA_S2C_GETDATA_LV1  10  //召唤一级数据功能码
#define FNA_S2C_GETDATA_LV2  11  //召唤二级数据功能码

//ASDU号定义
#define ASDU6_TIMESTAMP  6      // 对时
#define ASDU7_GETALL     7      // 总召唤，遥信
#define ASDU20_RESET     20     // 复归
#define ASDU21_GETGROUP  21     // 总召唤，要测
#define ASDU10_SETTING   10     // 数据回应，定值 0x0A
#define ASDU20_RESET     20     // 复归
#define ASDU21_GETGROUP  21     // 总召唤，遥测， 读取定值时使用  0x15 通用分类服务命令

//COT传送原因定义
//控制方向,以下全部为16进制
#define COT_S2C_TIMESTAMP     0x08      //时间同步
#define COT_S2C_GETALL_START  0x09      //总查询(总召唤)的启动
#define COT_S2C_COMMON_ORDER  0x14   //一般命令
#define COT_S2C_GENERAL_WRITE 0x28   //通用分类写命令
#define COT_S2C_GENERAL_READ  0x2A   //通用分类读命令


//FUN定义
#define FUN_GLB 0xFF       //全局功能类型 ASDU 主：6,7,20,24,25, 从：5,23,26,27,28,29,30,31
#define FUN_GEN 0xFE       //通用分类服务功能类型 ASDU主:10,21； 从：10

//INF（信息序号）定义
#define INF_RESET_ORDER   0x13  //复归命令，所有装置相同
#define INF_READ_GROUP    0xF1  //读一个组的全部条目的值或者属性 INF=241, ASDU=21
#define INF_READ_EBTRY    0xF4  //读一个条目的值或者属性，单项定值的读取 INF=244, ASDU=21
#define INF_CONFIRM_WRITE 0xF9  //带确认的写条目，定值下发时使用   INF=249, ASDU=10
#define INF_EXEC_WRITE    0xFA  //带执行的写条目，定值固化时采用   INF=250, ASDU=10

// 数据类型定义
#define DATA_TYPE_INT 0x04
#define DATA_ASCII_8 0X01
#define DATA_TYPE_BOOL 0X02
#define DATA_TYPE_UINT 0X03
#define DATA_TYPE_INT   0x04
#define DATA_TYPE_FLOAT 0X06
#define DATA_TYPE_SHORT_NUM 0X07
#define MAX_SIZE 1024

typedef struct {
    uint8_t fcb; // 桢记数位
    uint8_t fcv; // 桢记数有效位
} IEC103CodeS2C;

union UnionConvert4Byte
{
    unsigned int uValue;
    float fValue;
    char buf[4];
};

union UnionConvert2Byte
{
    short  value;
    unsigned short uValue;
    char buf[2];
};

// 定值读取和写入需要使用
typedef struct
{
    //通用分类标识序号GIN
    uint8_t groupNo;    //组号
    uint8_t entryNo;    //条目号

    //描述的类别KOD
    uint8_t kod;        //1为实际值

    //通用分类数据描述GDD
    uint8_t datatype;   //数据类型
    uint8_t datasize;   //数据宽度
    uint8_t number:7,   //数目
            cont:1;     //后续状态位
}stDataUnit;     //通用分类数据单元


typedef struct
{
    uint16_t msec;              //毫秒
    uint8_t  min:6,             //分钟
             res1:1,		    //备用
             iv:1;              //IV=0为有效  =1为无效
    uint8_t  hour:7,            //小时
             su:1;              //su夏时制标志
    uint8_t  day:5,             //日
             dayofweek:3;       //未采用
    uint8_t  month:4,           //月
             res2:4;            //备用
    uint8_t  year:7,            //年
             res3:1;            //备用
}stTime7Byte;

// 带品质描述词的被测量(MEA)
typedef struct {
    union {
        short	mval:13,	// 带符号规一化定点数，最高位符合位，数据位占12位
                res:1,		// 备用位:未用(常为0)
                er:1,		// 差错位:0-有效，1-无效
                ov:1;		// 溢出位:0-无溢出，1-溢出
        short   wVal;
    }mea;
}MEA;


// 报文解析结果缓存用结构体，一个定值组一个  BillTableStruct ，对应界面显示数据
struct BillTableStruct {
    QString groupNo;    // 组号
    QString groupName;  // 组名
     // 组具体条目各项信息
    QStringList billGinNoList;  // 条目信息
    QStringList billNameList;
    QStringList billRealValueList;
    QStringList billDefaultValueList;
    QStringList billUnitList;
    QStringList billMinList;
    QStringList billMaxList;
    QStringList billStepsList;
    QStringList billTypeList;
};

#endif /* IEC103TYPE_H_ */

